package ro.inf.bomberman;

/**
 * Bietet alle Methoden an, die zum Erstellen, Verwalten und Explodieren des
 * Feldobjekts Bombe benötigt werden.
 *
 * @author Felix
 */
public class Bomb extends Explosion implements Drawable {

    private Size size;
    private final Coordinate coords;
    private long timeExplodes; // Systemzeit, zu der die Bombe explodieren soll.
    private int spielerNr;

    /**
     * Konstruktor
     *
     * @author Felix
     * @param coordinates
     * @param spielfeld
     * @param explosionTime
     * @param spielerNr
     */
    public Bomb(Coordinate coordinates, GameField spielfeld, int explosionTime, int spielerNr) {
        super(coordinates, spielfeld, explosionTime);
        this.coords = coordinates;
        this.size = new Size(40, 40);
        this.spielerNr = spielerNr;
        this.timeExplodes = System.currentTimeMillis() + explosionTime;
        this.spielfeld.mapCoordToField(new Coordinate(this.coords.getX(), this.coords.getY())).registerBomb(this);
    }

    // ~~~~~~~~~~~~  getMethoden ~~~~~~~~~~~~
    /**
     * Gibt die Größe der Bombe als Size zurück.
     *
     * @author Felix
     * @return Size
     */
    public Size getSize() {
        return this.size;
    }

    /**
     * Gibt die Nummer des Spielers zurück, der die Bombe gelegt hat.
     *
     * @author Felix
     * @return int
     */
    public int getSpielerNr() {
        return this.spielerNr;
    }

    /**
     * Gibt die Position der Bombe als Coordinate zurück.
     *
     * @author Felix
     * @return Coordinate
     */
    public Coordinate getPosition() {
        return this.coords;
    }

    /**
     * Gibt die Zeit an der die Bombe gelegt wurde zurück.
     *
     * @author Felix
     * @return long
     */
    public long getTimeExplodes() {
        return this.timeExplodes;
    }

    // ~~~~~~~~~~~~  setMethoden ~~~~~~~~~~~~	
    /**
     * Setzt die Zeit, zu der die Bombe explodieren soll.
     *
     * @param newTime
     */
    public void setTimeExplodes(long newTime) {
        this.timeExplodes = newTime;
    }

    // ~~~~~~~~~~~~  explode() Methode ~~~~~~~~~~~~
    /**
     * Löscht ein Objekt auf dem Feld der Bombe, falls vorhanden. Löscht im
     * Bereich des Radius in Kreuzform alle Objekte. Falls die Explosion auf ein
     * Objekt trifft, stoppt sie an der Stelle in dieser Richtung.
     *
     * @author Felix
     */
    public void explode() {

        Coordinate tempc = new Coordinate(this.getPosition().getX(), this.getPosition().getY());
        boolean tempBlockExploded = false;
        int i = 1;

        if (this.spielfeld.mapCoordToField(this.getPosition()).containsObject() == true
                && this.spielfeld.mapCoordToField(this.getPosition()).getRegisteredObject() instanceof Player) {
            ((Player) this.spielfeld.mapCoordToField(this.getPosition()).getRegisteredObject()).explode();
        }

        // Prüft im horizontalen Radius nach Objekten und Bomben ab und lässt gegebenen Falls explodieren.
        while (i <= this.getRadius() && tempBlockExploded == false) {
            tempc.setX(this.getPosition().getX() + i * 40);
            if (this.spielfeld.mapCoordToField(tempc).containsObject() == true
                    && this.spielfeld.mapCoordToField(tempc).getRegisteredObject() instanceof Block) {
                ((Block) this.spielfeld.mapCoordToField(tempc).getRegisteredObject()).explode();
                tempBlockExploded = true;
            } else if (this.spielfeld.mapCoordToField(tempc).containsObject() == true
                    && this.spielfeld.mapCoordToField(tempc).getRegisteredObject() instanceof Player) {
                ((Player) this.spielfeld.mapCoordToField(tempc).getRegisteredObject()).explode();
                tempBlockExploded = true;
            }
            if (this.spielfeld.mapCoordToField(tempc).containsBomb() == true) {
                ((Bomb) this.spielfeld.mapCoordToField(tempc).getRegisteredBomb()).setTimeExplodes(System.currentTimeMillis() + 10);
                tempBlockExploded = true;
            }
            i++;
        }
        i = 1;
        tempBlockExploded = false;
        while (i <= this.getRadius() && tempBlockExploded == false) {
            tempc.setX(this.getPosition().getX() - i * 40);
            if (this.spielfeld.mapCoordToField(tempc).containsObject() == true
                    && this.spielfeld.mapCoordToField(tempc).getRegisteredObject() instanceof Block) {
                ((Block) this.spielfeld.mapCoordToField(tempc).getRegisteredObject()).explode();
                tempBlockExploded = true;
            } else if (this.spielfeld.mapCoordToField(tempc).containsObject() == true
                    && this.spielfeld.mapCoordToField(tempc).getRegisteredObject() instanceof Player) {
                ((Player) this.spielfeld.mapCoordToField(tempc).getRegisteredObject()).explode();
                tempBlockExploded = true;
            }
            if (this.spielfeld.mapCoordToField(tempc).containsBomb() == true) {
                ((Bomb) this.spielfeld.mapCoordToField(tempc).getRegisteredBomb()).setTimeExplodes(System.currentTimeMillis() + 10);
                tempBlockExploded = true;
            }
            i++;
        }

        //Prüft im vertikalen Radius nach Objekten und Bomben ab und lässt gegebenen falls explodieren explodieren.
        tempc.setX(this.getPosition().getX());
        i = 1;
        tempBlockExploded = false;
        while (i <= this.getRadius() && tempBlockExploded == false) {
            tempc.setY(this.getPosition().getY() + i * 40);
            if (this.spielfeld.mapCoordToField(tempc).containsObject() == true
                    && this.spielfeld.mapCoordToField(tempc).getRegisteredObject() instanceof Block) {
                ((Block) this.spielfeld.mapCoordToField(tempc).getRegisteredObject()).explode();
                tempBlockExploded = true;
            } else if (this.spielfeld.mapCoordToField(tempc).containsObject() == true
                    && this.spielfeld.mapCoordToField(tempc).getRegisteredObject() instanceof Player) {
                ((Player) this.spielfeld.mapCoordToField(tempc).getRegisteredObject()).explode();
                tempBlockExploded = true;
            }
            if (this.spielfeld.mapCoordToField(tempc).containsBomb() == true) {
                ((Bomb) this.spielfeld.mapCoordToField(tempc).getRegisteredBomb()).setTimeExplodes(System.currentTimeMillis() + 10);
                tempBlockExploded = true;
            }
            i++;
        }
        i = 1;
        tempBlockExploded = false;
        while (i <= this.getRadius() && tempBlockExploded == false) {
            tempc.setY(this.getPosition().getY() - i * 40);
            if (this.spielfeld.mapCoordToField(tempc).containsObject() == true
                    && this.spielfeld.mapCoordToField(tempc).getRegisteredObject() instanceof Block) {
                ((Block) this.spielfeld.mapCoordToField(tempc).getRegisteredObject()).explode();
                tempBlockExploded = true;
            } else if (this.spielfeld.mapCoordToField(tempc).containsObject() == true
                    && this.spielfeld.mapCoordToField(tempc).getRegisteredObject() instanceof Player) {
                ((Player) this.spielfeld.mapCoordToField(tempc).getRegisteredObject()).explode();
                tempBlockExploded = true;
            }
            if (this.spielfeld.mapCoordToField(tempc).containsBomb() == true) {
                ((Bomb) this.spielfeld.mapCoordToField(tempc).getRegisteredBomb()).setTimeExplodes(System.currentTimeMillis() + 10);
                tempBlockExploded = true;
            }
            i++;
        }
        this.spielfeld.mapCoordToField(this.getPosition()).removeBomb(this);
    }
}